function HandleHistoryMailInformation(gui, operator, now, options) {
  this._gui = gui;
  this._operator = operator;
  this._now = now;
  this._options = options;
  
  this._produceId = (options && options.p) ? options.p : null;

  this._popupBox = new PopupBox();
  this._popupBox2 = new PopupBox2();
  
  this._createElements();
};

HandleHistoryMailInformation.prototype._createElements = function() {
  var pos = [window.screen.width / 2, window.screen.height / 5];
  MiscUtils.load(this._popupBox, pos, 'It may take several seconds. Please wait...');
  
  this._loadData();
};

HandleHistoryMailInformation.prototype._verifyData = function() {
  if (this._produce) {
    this._updateElements();
  }
};

HandleHistoryMailInformation.prototype._loadData = function() {
  this._produce = null;
  
  this._retrieveProduces();
};

HandleHistoryMailInformation.prototype._retrieveProduces = function() {
  var _self = this;
  var joins = '&selects=0' + '&purchaseitems=0' + '&preconusers=0' + '&events=0' + '&tracks=0' + '&produces=1' + '&notes=0';
  var args = '&c=d.e_oid =' + this._produceId + joins;
  new RequestUtils()._mysql('produce', args, function(result, params) { _self._produce = (result.data.length == 1) ? result.data[0] : null;
                                                                        _self._verifyData.call(_self);
                                                                      }, { php: Constant.FACTORY + '/customphp/produceread.php'});
};

HandleHistoryMailInformation.prototype._updateElements = function() {
  
  var _self = this;
  DlmanageUtils.clear(this._gui);
  this._popupBox._close();
  
  if (this._operator.type == Constant.USER_TYPE_MANAGER_ASSISTANT) {
    var smryGui = GuiSmryAsst.instance();
    if (smryGui && smryGui.jobs) {
      var smryArgs = [ { name: smryGui.jobs.id, cond: DlmanageUtils.asstTasks + ' OR ' + '(' + DlmanageUtils.customWorks + ' AND ((d.ownerTrackId = \'' + this._operator.trackId + '\') OR (d.user_trackId = \'' + this._operator.trackId + '\'))' + ')'}
                     ];
      new HandleSmry(smryGui, null, { args: smryArgs });
    }
  } else if (this._operator.type == Constant.USER_TYPE_CUSTOMER_SERVICE) {
    var smryGui = GuiSmryServ.instance();
    if (smryGui && smryGui.jobs) {
      var smryArgs = [ { name: smryGui.jobs.id, cond: DlmanageUtils.servTasks + ' OR ' + '(' + DlmanageUtils.customWorks + ' AND ((d.ownerTrackId = \'' + this._operator.trackId + '\') OR (d.user_trackId = \'' + this._operator.trackId + '\'))' + ')'}
                     ];
      new HandleSmry(smryGui, null, { args: smryArgs });
    }
  }
  
  if (this._produce.state == 1) {
    var model, state, transitions = [], a, button, _self = this;
    
    model = Manage.map()[this._produce.pi_model];
    for (var i = 0, il = model.states.length; i < il; i++) {
      var s = model.states[i];
      if (this._produce.state == s.id) {
        state = s;
        break;
      }
    }
    
    for (var i = 0, il = model.transitions.length; i < il; i++) {
      var t = model.transitions[i];
      if (this._produce.state == t.source.id && t.validate(this._produce, this._operator, this._now, null)) {
        transitions[transitions.length] = t;
      }
    }
    
    if (transitions.length > 0) {
      this._gui.receive._transition = transitions[0];
      this._gui.receive.onclick = function() { var err = false, str = '';
                                               for (var i = 0, il = _self._produce.v2_produces.length; i < il; i++) {
                                                 var p = _self._produce.v2_produces[i];
                                                 if (!p._received) {
                                                   err = true;
                                                   str += p.title + ', ';
                                                 }
                                               }
                                               if (err) {
                                                 var context = this;
                                                 func1 = function() { if (_self._produce._text == '') {
                                                                        window.alert('CAN NOT BE EMPTY');
                                                                        return;
                                                                      }
                                                                      context._transition.operate(DOMUtils.findPos(context), function() { history.back(); }, _self._produce, _self._operator, _self._now, { models: Manage.map(), extra: _self._produce._text });
                                                                      _self._popupBox2._close();
                                                                    }
                                                 var func2 = function() { _self._popupBox2._close(); };
                                                 pos = DOMUtils.findPos(this);
                                                 div = document.createElement('div');
                                                 MiscUtils.dialog(_self._popupBox2, pos, div, func1, func2, {t: 'LOST: ' + str.substring(0, str.length - 2)});
                                                 new DialogInput(div, _self._produce, { title: '' });
                                               } else {
                                                 this._transition.operate(DOMUtils.findPos(this), function() { history.back(); }, _self._produce, _self._operator, _self._now, { models: Manage.map() });
                                               }
                                             };
    }
  } else {
    this._gui.receive.style.display = 'none';
  }
  
  this._memo = {};
  this._gui.memo.onclick = function() { var pos = DOMUtils.findPos(this);
                                        var div = document.createElement('div');
                                        var func1 = function() { _self._produce.review = _self._memo._text;
                                                                 new RequestUtils()._mwrite('produce', [_self._produce], [], function() { _self._retrieveProduces.call(_self); }, {php: Constant.FACTORY + '/customphp/mysqlwrite.php', pos: pos });
                                                                 _self._popupBox2._close();
                                                               };
                                        var func2 = function() { _self._popupBox2._close(); };
                                        MiscUtils.dialog(_self._popupBox2, pos, div, func1, func2, {t: 'REVIEW'});
                                        new DialogInput(div, _self._memo, { title: '', default: _self._produce.review });
                                      }
  
  this._gui.cancel.onclick = function() { history.back(); };

  this._gui.mailNumber.appendChild(document.createTextNode(this._produce.code));
  this._gui.person.appendChild(document.createTextNode(this._produce.receiver));
  
  this._gui.sendTime.appendChild(document.createTextNode((this._produce.sentDate) ? SimpleDate.format(this._produce.sentDate) : ''));
  this._gui.receiveTime.appendChild(document.createTextNode((this._produce.receivedDate) ? SimpleDate.format(this._produce.receivedDate) : ''));
  
  this._gui.address.appendChild(document.createTextNode(this._produce.address));
  this._gui.mailNo.appendChild(document.createTextNode(this._produce.code));
  this._gui.company.appendChild(document.createTextNode(this._produce.company));
  this._gui.weight.appendChild(document.createTextNode(this._produce.weight));
  this._gui.comment.appendChild(document.createTextNode(this._produce.comment));
  
  this._gui.review.appendChild(document.createTextNode(this._produce.review));
  
  new TableProducts(this._gui.products, this._produce.v2_produces, { user: this._operator, date: this._now, callbackFunc: function() { _self._updateElements.call(_self); } });
};